package cms.web.action;

import cms.common.data.ApiResult;
import cms.common.exception.InvalidActException;
import cms.common.exception.NoLoginException;
import cms.common.exception.ServiceException;
import cms.web.util.HttpServletUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.request.NativeWebRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

import static cms.common.data.ApiResultCode.FAILURE;
import static cms.common.data.ApiResultCode.NO_LOGIN_SUCCESS;


/**
 * Created by moueimei on 2017/5/12.
 */
@Slf4j
@ControllerAdvice
public class BaseExceptionAdvice {

    /**
     * 将map转换成url
     *
     * @param map
     * @return
     */
    public static String getUrlParamsByMap(Map<String, Object> map) {
        if (map == null || map.isEmpty()) {
            return "";
        }
        StringBuffer sb = new StringBuffer("?");
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Object valueObj = entry.getValue();
            if (null == valueObj) {
                sb.append(entry.getKey() + "=");
            } else if (valueObj instanceof String[]) {
                String[] values = (String[]) valueObj;
                String value = null;
                for (int i = 0; i < values.length; i++) {
                    value = values[i] + ",";
                }
                value = value.substring(0, value.length() - 1);
                sb.append(entry.getKey() + "=" + value);
            } else {
                sb.append(entry.getKey() + "=" + valueObj.toString());
            }
            sb.append("&");
        }
        String s = sb.toString();
        if (s.endsWith("&")) {
            s = StringUtils.substringBeforeLast(s, "&");
        }
        return s;
    }

    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(Exception.class)
    public String processException(NativeWebRequest nativeWebRequest, Exception e) {
        HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);//③
        String url = request.getRequestURL().toString();
        String param = getUrlParams(nativeWebRequest);
        log.error("url={}入参={}系统异常:", url, param, e);
        if (HttpServletUtils.isAjaxRequest(request)) {
            HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);
            HttpServletUtils.outJson(response, ApiResult.buildFailure(FAILURE).setData(url));
            return null;
        }
        nativeWebRequest.setAttribute("url", url + param, NativeWebRequest.SCOPE_REQUEST);
        nativeWebRequest.setAttribute("error", "[错误信息]：" + e.getMessage(), NativeWebRequest.SCOPE_REQUEST);
        return "/error/exception";
    }

    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(ServiceException.class)
    public String processException(NativeWebRequest nativeWebRequest, ServiceException e) {
        HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);//③
        String url = request.getRequestURL().toString();
        String param = getUrlParams(nativeWebRequest);
        log.error("url={}入参={}异常={}系统异常", url, param, e.toString(), e);
        if (HttpServletUtils.isAjaxRequest(request)) {
            HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);
            HttpServletUtils.outJson(response, ApiResult.buildFailure(e.getCode(), e.getMsg()).setData(e.getData()));
            return null;
        }
        nativeWebRequest.setAttribute("url", url + param, NativeWebRequest.SCOPE_REQUEST);
        nativeWebRequest.setAttribute("error", "[错误信息]：" + e.getMessage(), NativeWebRequest.SCOPE_REQUEST);
        return "/error/exception";
    }

    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(InvalidActException.class)
    public String processInvalidActException(NativeWebRequest nativeWebRequest, InvalidActException e) {
        HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);//③
        String url = request.getRequestURL().toString();
        String param = getUrlParams(nativeWebRequest);
        log.error("url={}入参={}系统异常:", url, param, e);
        if (HttpServletUtils.isAjaxRequest(request)) {
            HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);
            HttpServletUtils.outJson(response, ApiResult.buildFailure(e.getCode(), e.getMsg()).setData(url));
            return null;
        }
        nativeWebRequest.setAttribute("url", url + param, NativeWebRequest.SCOPE_REQUEST);
        nativeWebRequest.setAttribute("error", "[错误信息]：" + e.getMessage(), NativeWebRequest.SCOPE_REQUEST);
        return "/error/exception";
    }


    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(NoLoginException.class)
    public String processException(NativeWebRequest nativeWebRequest, NoLoginException e) {
        HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);//③
        String url = request.getRequestURL().toString();
        String param = getUrlParams(nativeWebRequest);
        log.error("url={}{} 用户未登陆！", url, param);
        boolean isAjax = HttpServletUtils.isAjaxRequest(request);
        if (isAjax) {
            HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);
            HttpServletUtils.outJson(response, ApiResult.buildFailure(NO_LOGIN_SUCCESS).setData(url));
            return null;
        }
        return "redirect:/shop/login.html";
    }


    private String getUrlParams(NativeWebRequest nativeWebRequest) {
        HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);//③
        Map map = request.getParameterMap();
        return getUrlParamsByMap(map);
    }


}
